﻿Shader "CCGame/Grass"
{
    Properties
    {
        [header(Main Colr)]
        _BaseColor("BaseColor", Color) = (1,1,1,1)
        _GroundColor("GroundColor", Color) = (0.5,0.5,0.5)
        
        
        [header(Grass Shape)]
        _GrassWidth("GrassWidth",Float) =1
        _GrassHeight("GrassHeight",Float) =1
        
        [header(Wind)]
        _WindFrequency1("WindFrequency", Float) = 4
        _WindIntensity1("WindIntensity",Float) = 1.77
        _WindDir1("WindDir",Vector) = (0.1,0.1, 0, 0)
        
        
        _WindFrequency2("WindFrequency", Float) = 7.7
        _WindIntensity2("WindIntensity",Float) =0.25
        _WindDir2("WindDir",Vector) = (0.37,0.3, 0, 0)
        
        
        _WindFrequency3("WindFrequency", Float) = 11.7
        _WindIntensity3("WindIntensity",Float) = 0.124
        _WindDir3("WindDir",Vector) = (0.77,3, 0, 0)
        
         [Header(Lighting)]
        _RandomNormal("_RandomNormal", Float) = 0.15
        
        [HideInInspector]_PivotPosWS("PivotPosWS", Vector) = (0,0,0,0)
        [HideInInspector]_BoundSize("BoundSize",Vector) = (1,1,0)
        
        
    }
    SubShader
    {
        Tags { "RenderType"="Opaque" "RenderPipeline" = "UniversalRenderPipeline"}
        LOD 100

        Pass
        {
           Cull Back
           ZTest Less
           Tags { "LightMode" = "UniversalForward" }
           
           HLSLPROGRAM
           
           #pragma vertex vert
           #pragma fragment frag
           
             // -------------------------------------
            // Universal Render Pipeline keywords
            // When doing custom shaders you most often want to copy and paste these #pragmas
            // These multi_compile variants are stripped from the build depending on:
            // 1) Settings in the URP Asset assigned in the GraphicsSettings at build time
            // e.g If you disabled AdditionalLights in the asset then all _ADDITIONA_LIGHTS variants
            // will be stripped from build
            // 2) Invalid combinations are stripped. e.g variants with _MAIN_LIGHT_SHADOWS_CASCADE
            // but not _MAIN_LIGHT_SHADOWS are invalid and therefore stripped.
            #pragma multi_compile _ _MAIN_LIGHT_SHADOWS
            #pragma multi_compile _ _MAIN_LIGHT_SHADOWS_CASCADE
            #pragma multi_compile _ _ADDITIONAL_LIGHTS_VERTEX _ADDITIONAL_LIGHTS
            #pragma multi_compile _ _ADDITIONAL_LIGHT_SHADOWS
            #pragma multi_compile _ _SHADOWS_SOFT
            // -------------------------------------
            // Unity defined keywords
            #pragma multi_compile_fog
            // -------------------------------------
    
            #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
            #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Lighting.hlsl"
           
           struct Attributes{
                float4 positionOS  : POSITION;
           };
           
           struct Varyings{
                float4 positionCS : SV_POSITION;
                half3 color       : COLOR;
           };
           
           CBUFFER_START(UnityPerMaterial)
             
 
                float _GrassWidth;
                float _GrassHeight;
                
                
                
                half3 _BaseColor;
                half3 _GroundColor;
                
                float _WindFrequency1;
                float2 _WindDir1;
                float _WindIntensity1;
                
                float _WindFrequency2;
                float2 _WindDir2;
                float _WindIntensity2;
                
                float _WindFrequency3;
                float2 _WindDir3;
                float _WindIntensity3;
                
                float3 _PivotPosWS;
                float2 _BoundSize; 
                
                float _RandomNormal;
                
                
                StructuredBuffer<float3> _GrassAllPosBuffer; // 全部草地的位置
                StructuredBuffer<uint> _GrassVisibleIDBuffer; // 全部可见草的id
                
           CBUFFER_END
        
           sampler2D _GrassBendingRT;
            
            
          
            half3 ApplySingleDirectLight(Light light, half3 N, half3 V, half3 albedo, half positionOSY){
                half3 H = normalize(light.direction + V);
                
                half directDiffuse = dot(N, light.direction) * 0.5 + 0.5;
                
                float directSpecular = saturate(dot(N, H));
                
                directSpecular *= directSpecular;
                directSpecular *= directSpecular;
                directSpecular *= directSpecular;
                
               directSpecular *= 0.1 * positionOSY;
               
               half3 lighting = light.color * (light.shadowAttenuation * light.distanceAttenuation);
               half3 result = (albedo * directDiffuse + directSpecular) * lighting;
               return result;
            }
            
           
           Varyings vert(Attributes input , uint instanceID : SV_InstanceId){
                Varyings output;
                
                float3  perGrassPivotPosWS = _GrassAllPosBuffer[_GrassVisibleIDBuffer[instanceID]].xyz ;
                
                float perGrassheight = lerp(2, 5, (sin(perGrassPivotPosWS.x * 23.4643 + perGrassPivotPosWS.z) * 0.35 + 0.55)) * _GrassHeight;
                
                
                  //rotation(make grass LookAt() camera just like a billboard)
                //=========================================
                float3 cameraTransformRightWS = UNITY_MATRIX_V[0].xyz;//UNITY_MATRIX_V[0].xyz == world space camera Right unit vector
                float3 cameraTransformUpWS = UNITY_MATRIX_V[1].xyz;//UNITY_MATRIX_V[1].xyz == world space camera Up unit vector
                float3 cameraTransformForwardWS = -UNITY_MATRIX_V[2].xyz;//UNITY_MATRIX_V[2].xyz == -1 * world space camera Forward unit vector

                float3 positionOS = input.positionOS.x * cameraTransformRightWS * _GrassWidth * (sin(perGrassPivotPosWS.x * 95.4643 + perGrassPivotPosWS.z) * 0.45 + 0.55);
                
                
                positionOS += input.positionOS.y * cameraTransformUpWS;
                
              
                // bending 
                //float2 grassBendingUV = (perGrassPivotPosWS.xz - _PivotPosWS.xz)/_BoundSize * 0.5 + 0.5;
            //    float stepped = tex2Dlod(_GrassBendingRT, float4(grassBendingUV, 0,0)).x;
              //  float3 bendDir = cameraTransformForwardWS;
                //bendDir.xz *= 0.5;
                //bendDir.y = min(-0.5, bendDir.y);
                //positionOS = lerp(positionOS.xyz + bendDir * positionOS.y / -bendDir.y, positionOS.xyz, stepped * 0.95 + 0.05);
                
                
                positionOS.y *= perGrassheight;
                
                float3 viewWS  = _WorldSpaceCameraPos - perGrassPivotPosWS;
                float viewWSLength = length(viewWS);
                positionOS += cameraTransformRightWS * input.positionOS.x * max(0, viewWSLength * 0.0225);
                
                float3 positionWS = positionOS + perGrassPivotPosWS;
                
                
                // 处理风
               float wind = 0;
                //wind += sin(_Time.y * _WindFrequency1 + perGrassPivotPosWS.x * _WindDir1.x + perGrassPivotPosWS.z * _WindDir1.y) * _WindIntensity1;
                //wind += sin(_Time.y * _WindFrequency2 + perGrassPivotPosWS.x * _WindDir2.x + perGrassPivotPosWS.z * _WindDir2.y) * _WindIntensity2;
                //wind += sin(_Time.y * _WindFrequency3 + perGrassPivotPosWS.x * _WindDir3.x + perGrassPivotPosWS.z * _WindDir3.y) * _WindIntensity3;
                
                //wind  *= input.positionOS.y;
                //float3 windOffset = cameraTransformRightWS * wind;
                //positionWS += windOffset;
                
                output.positionCS = TransformWorldToHClip(positionWS);
            
                // 在顶点处理光照
                Light mainLight;
                
#if _MAIN_LIGHT_SHADOWS
                mainLight = GetMainLight(TransformWorldToShadowCoord(positionWS));
#else
                mainLight = GetMainLight();
#endif
                half3 randomAddtoN = (_RandomNormal * sin(perGrassPivotPosWS.x * 82.32523 + perGrassPivotPosWS.x) + wind * -0.25) * cameraTransformRightWS;
                
                half3 N = normalize(half3(0,1,0) + randomAddtoN - cameraTransformRightWS * 0.5);
               
                half3 V = viewWS / viewWSLength;
                half3 albedo = lerp(_GroundColor, _BaseColor, input.positionOS.y);
                
                half3 lightingResult = SampleSH(0)  * albedo;
                lightingResult += ApplySingleDirectLight(mainLight, N, V, albedo, positionOS.y);
                
#if _ADDITIONAL_LIGHTS
                int additionalLightsCount = GetAdditionalLightsCount();
                for (int i = 0; i < additionalLightsCount; ++i)
                {
                    // Similar to GetMainLight, but it takes a for-loop index. This figures out the
                    // per-object light index and samples the light buffer accordingly to initialized the
                    // Light struct. If _ADDITIONAL_LIGHT_SHADOWS is defined it will also compute shadows.
                    Light light = GetAdditionalLight(i, positionWS);

                    // Same functions used to shade the main light.
                    lightingResult += ApplySingleDirectLight(light, N, V, albedo, positionOS.y);
                }
#endif        
                float fogFactor = ComputeFogFactor(output.positionCS.z);
                output.color = MixFog(lightingResult, fogFactor);
                 
            
                return output;
           }
           
           half4 frag(Varyings input) : SV_Target{
                return  half4(input.color, 1);
           }
           
           ENDHLSL
        }
    }
}
